/*
 * Copyright (c) 2018  菠菜数块链版权所有.
 */
package com.otherTest.reflect;


import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.stream.Stream;

/**
 * @Description: 反射测试
 * @author: conceit
 * @Date: 2018/9/19 0019 14:06
 */
public class ReflectMainTest {

    public static void main(String[] args) throws NoSuchMethodException, NoSuchFieldException, InstantiationException, IllegalAccessException, InvocationTargetException {
        new ReflectMainTest().doTestReflect3();
    }

    /**
     * @Description: doTestReflect1获取class的三种方法
     * 对于每个类而言，java都为其保留一个不变的 Class 类型的对象
     * 一个类（而不是一个对象）在 JVM 中只会有一个Class实例
     * <p>
     * 1-通过类名获取 类名.class
     * 2-通过对象获取 对象名.getClass()
     * 3-通过全类名获取 Class.forName(全类名)
     * 第三种比较常用
     * @params []
     * @author: conceit
     * @return: void
     * @Date: 2018/9/19 0019 14:11
     */
    @Test
    public void doTestReflect1() throws ClassNotFoundException {
        Class clazz = null;


        System.out.println("类名.class-->" + ReflectObject.class);
        ReflectObject reflectObject = new ReflectObject();

        System.out.println("对象名.getClass()-->" + reflectObject.getClass());

        System.out.println("Class.forName(全类名)-->" + Class.forName("com.otherTest.reflect.ReflectObject"));
    }

    /**
     * @Description: doTestReflect2 反射属性相关的方法
     * @params []
     * @author: conceit
     * @return: void
     * @Date: 2018/9/20 0020 10:18
     */
    @Test
    public void doTestReflect2() throws ClassNotFoundException, IllegalAccessException {
        Class clazz = Class.forName("com.otherTest.reflect.ReflectObject");
        //private和public 都可以获取
        for (Field field : clazz.getDeclaredFields()) {

            System.out.println("属性名-->" + field.getName());

            //获取属性的标识符，类型，全类名.方法名
            System.out.println("属性通用类型-->" + field.toGenericString());
            System.out.println("属性类型-->" + field.getType());
            System.out.println("属性所属类-->" + field.getDeclaringClass());
            System.out.println("属性的所有注解名");
            Stream.of(field.getDeclaredAnnotations()).forEach(System.out::println);

            field.setAccessible(true);
            //System.out.println("获取静态属性或实例的值-->"+field.get(null));
            System.out.println("----------------------------------------------------------------");
        }


    }

    /**
     * @Description: doTestReflect3对方法的相关方法
     * 用date1对应 属性date1 并对其赋值
     * @params []
     * @author: conceit
     * @return: void
     * @Date: 2018/9/20 0020 11:26
     */
    @Test
    public  void doTestReflect3() throws InvocationTargetException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InstantiationException {
        ReflectObject reflectObject=new ReflectObject();
        reflectObject.setId("id");
        System.out.println("替换前--》"+reflectObject);

        String date1="date1";

        Class clazz = reflectObject.getClass();

        //获得某个类的所有声明的字段，即包括public、private和proteced，但是不包括父类的申明字段
        for (Field field : clazz.getDeclaredFields()) {
            //System.out.println(field.getName());
        }
        //获得某个类的所有的公共（public）的字段，包括父类中的字段
        for(Field field :clazz.getFields()){
            //System.out.println(field);
        }

        //获得某个类的所有的公共（public）的构造方法
        for (Constructor constructor:clazz.getConstructors()){
            //System.out.println(constructor);
        }

        for (Constructor constructor:clazz.getDeclaredConstructors()){
            //System.out.println(constructor);
        }

        //获得某个类的所有的方法
        for (Method method: clazz.getDeclaredMethods()){
            //System.out.println(method.getName());
        }

        //替换属性为date1 的值
        //匹配所有方法
        //有相等的则 映射到set+date1(D大写)的方法上,并执行
        Field field=clazz.getDeclaredField(date1);
        //Stream.of(clazz.getDeclaredFields()).filter(fields -> fields.getName().equalsIgnoreCase(date1)).findFirst().get()
        //Stream.of(clazz.getDeclaredMethods()).filter(methods->methods.getName().equalsIgnoreCase(setDate1)).findFirst().get().invoke(date1);


//        String setDate1="set"+toUpperCaseFirstOne(date1);
//        System.out.println("该属性对应的方法为--》"+setDate1);
//        Method method=clazz.getDeclaredMethod(setDate1,String.class);
//        method.invoke(clazz,date1,String.class);
         field.setAccessible(true);
         field.set(reflectObject,"12345");


        System.out.println("替换后--》"+reflectObject);


    }

    //首字母转小写
    public static String toLowerCaseFirstOne(String s){
        if(Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }


    //首字母转大写
    public static String toUpperCaseFirstOne(String s){
        if(Character.isUpperCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
    }

}
